home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i175: MRARPFile 1.1 - routines to enhance ARP file-handling, Part02/02
- Message-ID: <12701@xanth.cs.odu.edu>
- Date: 3 Jun 90 23:30:54 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: mrr@amanpt1.Newport.RI.US (Mark Rinfret)
- Lines: 617
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
- X-Post-Discussions-To: comp.sys.amiga
-
- Submitted-by: mrr@amanpt1.Newport.RI.US (Mark Rinfret)
- Posting-number: Volume 90, Issue 175
- Archive-name: examples/mrarpfile-1.1/part02
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: MRARPFile.c
- # Wrapped by tadguy@xanth on Sun Jun 3 19:29:31 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MRARPFile.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MRARPFile.c'\"
- else
- echo shar: Extracting \"'MRARPFile.c'\" \(17486 characters\)
- sed "s/^X//" >'MRARPFile.c' <<'END_OF_FILE'
- X/* File support routines to complement ARP.
- X * Author: Mark R. Rinfret
- X * Usenet: mrr@amanpt1.Newport.RI.US
- X * BIX: markr
- X * CIS: 72017, 136 (good luck!)
- X *
- X * 348 Indian Avenue
- X * Portsmouth, RI 02871
- X * 401-846-7639 (home)
- X * 401-849-9390 (work)
- X *
- X * This package was written primarily because of _one_ missing element
- X * in ARP: FGets. ARGH! ARPFFFT! It extends ARP by adding buffering to
- X * the basic file type (FileHandle) and defining a new type, named
- X * ARPFileHandle (hope this is OK with the ARP guys). Also, I've used the
- X * convention of embedding ARP (vs. Arp in MicroSmith's stuff) in all type
- X * and function names to (hopefully) avoid naming collisions.
- X *
- X * This package (as far as I am concerned) is public domain. Use it any
- X * way you like. Some comments on the "MR" prefix: it isn't short for
- X * "Mister", it comprises the initials of my first and last names.
- X * I use it primarily to avoid name collisions with stuff by other
- X * authors. If any other authors whose initials are "MR" start doing
- X * this, we'll probably have to appeal to Electronic Arts to dole out
- X * "author codes" along the lines of those issued for IFF :-). I hereby
- X * stake a claim to 'MRR_'.
- X *
- X * A word of warning:
- X *
- X * DO NOT INTERMIX STANDARD AMIGADOS FILE SUPPORT CALLS WITH CALLS TO
- X * THIS PACKAGE ON FILES USING THIS FILE METHOD!
- X *
- X * Obviously, the system doesn't know about the buffering added here
- X * and will cause unpredictable results if you mix calls to this package
- X * with calls to Read/Write/Seek, etc. (unless, of course, you take care
- X * to maintain the ARPFileHandle information).
- X */
- X
- X
- X#if __STDC__
- X#include <stdlib.h>
- X#endif
- X
- X#include "MRARPFile.h"
- X#include <exec/memory.h>
- X#include <string.h>
- X#include <functions.h>
- X
- X#ifndef min
- X#define min(a,b) ((a) <= (b) ? (a) : (b))
- X#define max(a,b) ((a) >= (b) ? (a) : (b))
- X#endif
- X
- X/* struct DefaultTracker *StoreTracker __PARMS( (void) ); */
- X
- Xstatic LONG FillARPFileBuffer __PARMS( (ARPFileHandle *file) );
- Xstatic LONG FlushARPFileBuffer __PARMS( (ARPFileHandle *file) );
- X
- X/* FUNCTION
- X * FGetsARP - get string from a buffered ARP file.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * char *FGetsARP(s, length, file)
- X * UBYTE *s;
- X * LONG length;
- X * ARPFileHandle *file;
- X *
- X * DESCRIPTION
- X * FGetsARP models the behavior of the "standard" fgets, except that
- X * it is used with a buffered ARP file. The data is read from <file>
- X * and transfered to string <s>. Up to length-1 characters will be
- X * read. Reading is also terminated upon receipt of a newline
- X * or detection of end-of-file.
- X *
- X * If the <file> was opened without a buffer, one of MaxInputBuf
- X * bytes will be allocated.
- X *
- X * If end of file or an error is detected, the return value will be
- X * NULL. Otherwise, the return value will be <s>. <s> will be
- X * terminated with a null byte.
- X */
- Xchar *
- XFGetsARP(s, length, file)
- X char *s;
- X LONG length;
- X ARPFileHandle *file;
- X{
- X LONG bytesNeeded = length - 1;
- X LONG bytesRead = 0;
- X char c;
- X char *s1 = s;
- X
- X /* Set string initially empty to protect user from failure to check
- X * return value.
- X */
- X *s1 = '\0';
- X if (file->mode != MODE_OLDFILE)
- X file->lastError = ERROR_READ_PROTECTED;
- X
- X if (file->lastError) {
- Xdangit:
- X return NULL;
- X }
- X if (! file->buf ) { /* Ohmigosh! No buffer? */
- X file->buf = ArpAlloc(MaxInputBuf);
- X if (! file->buf ) {
- X file->lastError = ERROR_NO_FREE_STORE;
- X goto dangit;
- X }
- X file->bufSize = MaxInputBuf; /* bufLength, bufPos are zero. */
- X }
- X while (bytesNeeded) {
- X if (file->bufPos >= file->bufLength) {
- X if (FillARPFileBuffer(file) < 0) goto dangit;
- X if (file->bufLength == 0) break;
- X }
- X c = file->buf[file->bufPos++];
- X ++bytesRead;
- X if (c == '\n') break;
- X *s1++ = c;
- X --bytesNeeded;
- X }
- X *s1 = '\0';
- X return (bytesRead ? s : NULL);
- X}
- X
- X/* FUNCTION
- X * FillARPFileBuffer - read data into ARPFile buffer.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * static LONG FillARPFileBuffer(file)
- X * ARPFileHandle *file;
- X *
- X * DESCRIPTION
- X * Attempt to fill the buffer associated with <file> by reading
- X * data from the associated external file. The return value will
- X * be one of the following:
- X * >0 => number of bytes read
- X * 0 => end of file
- X * -1 => a Bad Thing happened (error code in file->lastError)
- X *
- X * Note: this is a local routine and is thus declared as "static".
- X * Please inform the author if this is a hardship.
- X */
- Xstatic LONG
- XFillARPFileBuffer(file)
- X ARPFileHandle *file;
- X{
- X /* Remember where we were. The user might want to try error
- X * recovery. Of course, this probably isn't enough info, but
- X * it's a start.
- X */
- X file->lastPosition = Seek(file->fh, 0L, OFFSET_CURRENT);
- X file->bufPos = 0;
- X file->bufLength = Read(file->fh, file->buf, file->bufSize);
- X if (file->bufLength == -1) { /* We got trubble! */
- X file->lastError = IoErr();
- X }
- X else if (file->bufLength == 0) {
- X file->endOfFile = TRUE;
- X }
- X return file->bufLength;
- X}
- X
- X/* FUNCTION
- X * FlushARPFileBuffer - write file buffer contents to disk.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * static LONG FlushARPFileBuffer(ARPFileHandle *file);
- X *
- X * DESCRIPTION
- X * FlushARPFileBuffer writes the contents of <file>'s buffer
- X * (if any) to disk and resets the buffer information. The
- X * return value may be any of:
- X *
- X * >0 => number of bytes written
- X * 0 => nothing in buffer
- X * <0 => negated error code
- X *
- X * Note: it is assumed that this function will only be used locally
- X * and therefore need not be public. If you disagree, please contact
- X * the author.
- X */
- X
- Xstatic LONG
- XFlushARPFileBuffer(file)
- X ARPFileHandle *file;
- X{
- X LONG bytesWritten = 0;
- X
- X /* This operation is only allowed for output files. */
- X
- X if (file->mode != MODE_NEWFILE) {
- X file->lastError = ERROR_WRITE_PROTECTED;
- Xbadstuff:
- X return -file->lastError;
- X }
- X
- X if (file->lastError) goto badstuff; /* Residual error? */
- X
- X if (file->bufLength) {
- X file->lastPosition = Seek(file->fh, 0L, OFFSET_CURRENT);
- X bytesWritten = Write(file->fh, (const char *) file->buf, file->bufLength);
- X if (bytesWritten != file->bufLength) {
- X file->lastError = IoErr();
- X goto badstuff;
- X }
- X else {
- X file->bufLength = 0;
- X file->bufPos = 0;
- X }
- X }
- X return bytesWritten;
- X}
- X
- X/* FUNCTION
- X * FPutsARP - write a string to a buffered ARP file.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * LONG FPutsARP(s, file)
- X * char *s;
- X * ARPFileHandle *file;
- X *
- X * DESCRIPTION
- X * FPutsARP writes the contents of string <s> to the specified <file>.
- X * If successful, it returns 0. On failure, it returns the negated
- X * system error code.
- X */
- XLONG
- XFPutsARP(s, file)
- X char *s;
- X ARPFileHandle *file;
- X{
- X LONG bytesLeft, bytesUsed;
- X char *s1 = s;
- X
- X if (file->mode != MODE_NEWFILE)
- X file->lastError = ERROR_WRITE_PROTECTED;
- X
- X if (file->lastError) {
- Xshucks:
- X return -file->lastError;
- X }
- X
- X bytesLeft = strlen(s);
- X
- X /* Attempt to be smart about this transfer. Copy the string to the
- X * buffer in chunks. There is a possibility that the string is bigger
- X * than the size of the buffer.
- X */
- X while (bytesLeft) {
- X if (file->bufPos >= file->bufSize) {
- X if (FlushARPFileBuffer(file) <= 0) goto shucks;
- X }
- X bytesUsed = min(file->bufSize - file->bufPos, bytesLeft);
- X CopyMem(s1, &file->buf[file->bufPos], bytesUsed);
- X s1 += bytesUsed;
- X file->bufLength = (file->bufPos += bytesUsed);
- X bytesLeft -= bytesUsed;
- X }
- X return 0;
- X}
- X
- X/* FUNCTION
- X * ReadARPFile - read from a buffered ARP file.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * LONG ReadARPFile(ARPFileHandle *file, char *buffer, LONG length);
- X *
- X * DESCRIPTION
- X * ReadARPFile attempts to read <length> bytes from <file>, transferring
- X * the data to <buffer>.
- X *
- X * The return value may be any of the following:
- X *
- X * >0 number of bytes transferred
- X * 0 end of file
- X * <0 negated error code
- X *
- X * Note: if the lastError field of the <file> descriptor contains a
- X * non-zero value, its negated value will be returned and no
- X * attempt will be made to read the file. If you attempt error
- X * recovery, you must clear this field to zero.
- X */
- XLONG
- XReadARPFile(file, buffer, length)
- X ARPFileHandle *file;
- X char *buffer;
- X LONG length;
- X{
- X LONG bytesLeft;
- X LONG bytesRead = 0;
- X LONG needBytes = length;
- X LONG pos = 0;
- X LONG usedBytes = 0;
- X
- X /* Prevent read if this file opened for writing. */
- X
- X if (file->mode != MODE_OLDFILE)
- X file->lastError = ERROR_READ_PROTECTED;
- X
- X if (file->lastError) { /* Have residual error? */
- Xboofar:
- X return -file->lastError;
- X }
- X
- X if ( ! file->buf ) { /* No buffer? */
- X bytesRead = Read(file->fh, buffer, length);
- X if (bytesRead == -1) {
- X file->lastError = IoErr();
- X goto boofar;
- X }
- X }
- X else while (needBytes) {
- X if (file->bufLength - file->bufPos <= 0) {
- X if (FillARPFileBuffer(file) == -1) goto boofar;
- X if (file->bufLength == 0) break;
- X }
- X bytesLeft = file->bufLength - file->bufPos;
- X usedBytes = min(bytesLeft, length);
- X CopyMem(&file->buf[file->bufPos], &buffer[pos], usedBytes);
- X file->bufPos += usedBytes;
- X pos += usedBytes;
- X bytesRead += usedBytes;
- X needBytes -= usedBytes;
- X }
- X return bytesRead;
- X}
- X
- X/* FUNCTION
- X * CloseARPFile - close buffered ARP file.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * LONG CloseARPFile(file)
- X * ARPFileHandle *file;
- X *
- X * DESCRIPTION
- X * CloseARPFile closes the file described by <file> which MUST have
- X * been opened by OpenARPFile. It releases all tracked items
- X * associated with <file>, as well.
- X *
- X * The return value is only meaningful for output files. If, upon
- X * flushing the buffer, a write error is detected, a system error
- X * code (ERROR_DISK_FULL, etc.) will be returned.
- X */
- X
- XLONG
- XCloseARPFile(file)
- X ARPFileHandle *file;
- X{
- X LONG result = 0;
- X
- X if (file) { /* Just in case... */
- X if (file->fileTracker) {
- X /* Any left-over stuff in the buffer? If so, we must flush
- X * it to disk. However, if an error was detected in the
- X * previous operation, punt.
- X */
- X if ( ( file->mode == MODE_NEWFILE) &&
- X ! file->lastError &&
- X file->bufLength) {
- X if (Write(file->fh, (const char *) file->buf, file->bufLength) !=
- X file->bufLength)
- X result = IoErr();
- X }
- X FreeTrackedItem(file->fileTracker);
- X }
- X
- X FreeTrackedItem((struct DefaultTracker *) file->buf);
- X FreeTrackedItem((struct DefaultTracker *) file);
- X }
- X return result;
- X}
- X
- X/* FUNCTION
- X * OpenARPFile - open a buffered ARP file
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * struct MRARPFile *OpenARPFile(name, accessMode, bytes)
- X * char *name;
- X * LONG accessMode, bytes;
- X *
- X * DESCRIPTION
- X * OpenARPFile opens the file <name>, with the given <accessMode>
- X * (MODE_OLDFILE, MODE_NEWFILE only!) for buffered access. The
- X * size of the local buffer is specified by <bytes>.
- X *
- X * A zero value for <bytes> is OK and is sometimes appropriate, as
- X * when performing file copy operations, etc. However, if a file
- X * opened with a zero length buffer is then passed to the
- X * FGetsARP function, "spontaneous buffer allocation" will occur.
- X * No biggy, really, just something you should know. The ARP constant,
- X * MaxInputBuf will be used for the buffer size, in this case.
- X *
- X * If successful, a pointer to the file tracking structure is
- X * returned. Otherwise, the return value will be NULL.
- X *
- X * OpenARPFile uses full resource tracking for all information
- X * associated with the file.
- X *
- X */
- X
- XARPFileHandle *
- XOpenARPFile(name, accessMode, bytes)
- X char *name;
- X LONG accessMode, bytes;
- X{
- X BPTR fh;
- X ARPFileHandle *theFile = NULL;
- X struct DefaultTracker *lastTracker;
- X
- X /* This package does not support READ/WRITE access! */
- X
- X if ( (accessMode != MODE_OLDFILE) && (accessMode != MODE_NEWFILE))
- X return NULL;
- X
- X theFile = ArpAlloc((LONG) sizeof(ARPFileHandle));
- X if (theFile) {
- X theFile->mode = accessMode;
- X fh = ArpOpen(name, accessMode);
- X lastTracker = LastTracker;
- X if (!fh) {
- Xfungu:
- X CloseARPFile(theFile); /* Don't worry - it's "smart". */
- X theFile = NULL;
- X }
- X theFile->fileTracker = lastTracker;
- X theFile->fh = fh;
- X if ( bytes) { /* Does user want a buffer? */
- X theFile->buf = ArpAlloc(bytes);
- X if (!theFile->buf) goto fungu;
- X theFile->bufSize = bytes;
- X }
- X }
- X return theFile;
- X}
- X
- X/* FUNCTION
- X * SeekARPFile - move to new logical position in file.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * LONG SeekARPFile(file, position, mode)
- X * ARPFileHandle *file;
- X * LONG position;
- X * LONG mode;
- X *
- X * DESCRIPTION
- X * SeekARPFile attempts to position the <file> to a new logical
- X * position or report it's current position. The <position>
- X * parameter represets a signed offset. The <mode> parameter may
- X * be one of:
- X *
- X * OFFSET_BEGINNING (-1) => from beginning of file
- X * OFFSET_CURRENT (0) => from current position
- X * OFFSET_END (-1) => from end of file
- X *
- X * On output files, the current buffer contents, if any, are
- X * written to disk.
- X *
- X * The return value will either be a positive displacement >=0) or
- X * a negated system error code.
- X */
- XLONG
- XSeekARPFile(file, position, mode)
- X ARPFileHandle *file;
- X LONG position;
- X LONG mode;
- X{
- X LONG newPosition;
- X
- X if (file->mode == MODE_NEWFILE && file->bufLength) {
- X if (FlushARPFileBuffer(file) < 0) {
- Xfarboo:
- X return -file->lastError;
- X }
- X }
- X /* Remember our last position. */
- X file->lastPosition = Seek(file->fh, 0L, OFFSET_CURRENT);
- X if ((newPosition = Seek(file->fh, position, mode)) == -1) {
- X file->lastError = IoErr();
- X goto farboo;
- X }
- X return newPosition;
- X}
- X
- X/* FUNCTION
- X * WriteARPFile - write data to a buffered ARP file.
- X *
- X * SYNOPSIS
- X * #include <MRARPFile.h>
- X *
- X * LONG WriteARPFile(ARPFileHandle *file, const char *buffer, LONG length);
- X *
- X * DESCRIPTION
- X * WriteARPFile attempts to write <length> bytes from <buffer> to
- X * the buffered ARP file, <file>. The file MUST have been opened
- X * with OpenARPFile for MODE_NEWFILE access.
- X *
- X * WriteARPFile will not write to a file if the lastError field is
- X * non-zero, or if the file was opened for input.
- X *
- X * If successful, WriteARPFile will return the <length> parameter.
- X * Otherwise, it will return a negated system error code.
- X */
- XLONG
- XWriteARPFile(file, buffer, length)
- X ARPFileHandle *file;
- X const char *buffer;
- X LONG length;
- X{
- X LONG bufferBytes;
- X LONG bytesLeft = length;
- X LONG pos = 0;
- X LONG usedBytes = 0;
- X
- X if (file->mode != MODE_NEWFILE)
- X file->lastError = ERROR_WRITE_PROTECTED;
- X
- X if (file->lastError) { /* Catches mode and residual errors. */
- Xsumbidge:
- X return -(file->lastError);
- X }
- X
- X if ( ! file->buf ) { /* No buffer? */
- X if (Write(file->fh, buffer, length) != length) {
- X file->lastError = IoErr();
- X goto sumbidge;
- X }
- X }
- X else while (bytesLeft) {
- X /* Need to flush the file's buffer? */
- X if (file->bufPos >= file->bufSize) {
- X if (FlushARPFileBuffer(file) < 0) {
- X goto sumbidge;
- X }
- X }
- X bufferBytes = file->bufSize - file->bufPos;
- X usedBytes = min(bufferBytes, bytesLeft);
- X CopyMem(&buffer[pos], &file->buf[file->bufPos], usedBytes);
- X file->bufLength = (file->bufPos += usedBytes);
- X pos += usedBytes;
- X bytesLeft -= usedBytes;
- X }
- X return length;
- X}
- X
- X/* Embedded documentation template (cut & paste): */
- X
- X/* FUNCTION
- X *
- X * SYNOPSIS
- X *
- X * DESCRIPTION
- X *
- X */
- END_OF_FILE
- if test 17486 -ne `wc -c <'MRARPFile.c'`; then
- echo shar: \"'MRARPFile.c'\" unpacked with wrong size!
- fi
- # end of 'MRARPFile.c'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
- Mail comments to the moderator at <amiga-request@cs.odu.edu>.
- Post requests for sources, and general discussion to comp.sys.amiga.
-